package com.gisuni.sddc.util;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;



/**
 * HTTP通用方法
 * @author	yanggy
 * @version 0.1
 *
 */
public final class HttpUtil {
	
	private static final Log log = LogFactory.getLog(HttpUtil.class);
	
	/**
	 * Get请求
	 * @param url
	 * @return
	 * @throws IOException 
	 */
	public static String get(String url) throws IOException {
		CloseableHttpClient client = HttpClients.createDefault();
		HttpGet httpget = new HttpGet(url);
		CloseableHttpResponse response = client.execute(httpget);
		
		try {
			return EntityUtils.toString(response.getEntity());
		} catch (Exception e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		} finally {
			response.close();
			client.close();
		}
	}
	
	/**
	 * Get请求(将返回的流解析为字符串)
	 * @param url
	 * @return
	 * @throws IOException 
	 * @throws  
	 */
	public static String getStream(String url) throws IOException {
		String encode = "utf-8";
		CloseableHttpClient client = HttpClients.createDefault();
		HttpGet httpget = new HttpGet(url);
		httpget.addHeader("Content-Type", "application/octet-stream; charset=" + encode);
		CloseableHttpResponse response = client.execute(httpget);
		
		try {
			HttpEntity entity = response.getEntity();
			InputStream stream = entity.getContent();
			UnicodeInputStream uin = new UnicodeInputStream(stream, encode);
			InputStreamReader in = null;
			encode = uin.getEncoding();
			
			if (encode == null) {
				in = new InputStreamReader(uin);
			} else {
				in = new InputStreamReader(uin, encode);
			}
			BufferedReader reader = new BufferedReader(in);
			StringBuilder sb = new StringBuilder();
			String line;
			
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			in.close();
			return sb.toString();
		} catch (Exception e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		} finally {
			response.close();
			client.close();
		}
	}
	
	/**
	 * Post请求
	 * @param url
	 * @param params
	 * @return
	 * @throws IOException 
	 */
	public static String post(String url, Map<String, String> params) throws IOException {
		CloseableHttpClient client = HttpClients.createDefault();
		HttpPost httppost = new HttpPost(url);
		CloseableHttpResponse response = null;
		
		try {
			if (params != null) {
				List<NameValuePair> nvpList = new ArrayList<NameValuePair>();
				Iterator<String> iter = params.keySet().iterator();
				
				if (iter != null) {
					while (iter.hasNext()) {
						String key = iter.next();
						nvpList.add(new BasicNameValuePair(key, params.get(key)));
					}
					UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvpList, Consts.UTF_8);
					httppost.setEntity(entity);
				}
			}
			response = client.execute(httppost);
			return EntityUtils.toString(response.getEntity());
		} catch (Exception e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		} finally {
			if (response != null) {
				response.close();
			}
			client.close();
		}
	}
	
	/**
	 * Post请求(将返回的流解析为字符串)
	 * @param url
	 * @param params
	 * @param encode
	 * @return
	 * @throws IOException 
	 */
	public static String postStream(String url, Map<String, String> params) throws IOException {
		String encode = "utf-8";
		CloseableHttpClient client = HttpClients.createDefault();
		HttpPost httppost = new HttpPost(url);
		httppost.addHeader("Content-Type", "application/octet-stream; charset=" + encode);
		CloseableHttpResponse response = null;
		
		try {
			if (params != null) {
				List<NameValuePair> nvpList = new ArrayList<NameValuePair>();
				Iterator<String> iter = params.keySet().iterator();
				
				if (iter != null) {
					while (iter.hasNext()) {
						String key = iter.next();
						nvpList.add(new BasicNameValuePair(key, params.get(key)));
					}
					UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvpList, Consts.UTF_8);
					httppost.setEntity(entity);
				}
			}
			response = client.execute(httppost);
			HttpEntity entity = response.getEntity();
			InputStream stream = entity.getContent();
			UnicodeInputStream uin = new UnicodeInputStream(stream, encode);
			InputStreamReader in = null;
			encode = uin.getEncoding();
			
			if (encode == null) {
				in = new InputStreamReader(uin);
			} else {
				in = new InputStreamReader(uin, encode);
			}
			BufferedReader reader = new BufferedReader(in);
			StringBuilder sb = new StringBuilder();
			String line;
			
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			in.close();
			return sb.toString();
		} catch (IOException e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		} finally {
			if (response != null) {
				response.close();
			}
			client.close();
		}
	}
	
	/**
	 * 发送http请求，返回字符串
	 * @param method
	 * @param urlStr
	 * @param postData
	 * @return
	 */
	public static String sendRequest(String method, String urlStr, String postData) {
		HttpURLConnection conn = null;
		
		try {
			URL url = new URL(urlStr);
			conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(300000);
			conn.setReadTimeout(100000);
			conn.setRequestMethod(method);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(true);
			conn.setAllowUserInteraction(false);
			
			if (method.equalsIgnoreCase("POST")) {
				OutputStreamWriter wr = null;
				
				try {
					wr = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
					wr.write(postData);
				} catch (UnsupportedEncodingException e) {
					log.error(e.getMessage());
					
					if (wr != null) {
						wr.close();
					}
				} finally {
					if (wr != null) {
						wr.flush();
						wr.close();
					}
				}
			}
			return streamToString(conn.getInputStream(), "utf-8");
		} catch (IOException e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		} finally {
			if (conn != null) {
				conn.disconnect();
			}
		}
	}
	
	/**
	 * 发送http请求，返回流，需要在外部关闭连接
	 * @param conn
	 * @param method
	 * @param urlStr
	 * @param postData
	 * @return
	 */
	public static InputStream sendRequest2(HttpURLConnection conn, String method, String urlStr, String postData) {
		try {
			conn.setConnectTimeout(300000);
			conn.setReadTimeout(100000);
			conn.setRequestMethod(method);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(true);
			conn.setAllowUserInteraction(false);
			
			if (method.equalsIgnoreCase("POST")) {
				OutputStreamWriter wr = null;
				
				try {
					wr = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
					wr.write(postData);
				} catch (UnsupportedEncodingException e) {
					log.error(e.getMessage());
					
					if (wr != null) {
						wr.close();
					}
				} finally {
					if (wr != null) {
						wr.flush();
						wr.close();
					}
				}
			}
			return conn.getInputStream();
		} catch (IOException e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		}
	}

	/**
	 * 发送文件
	 * @param url
	 * @param file
	 * @return
	 */
	public static String sendFile(String url, File file) {
		String fromAgentResult = "";

		HttpClient client = new HttpClient();
		// client.getParams().setContentCharset("UTF-8");
		PostMethod filePost = new PostMethod(url);
		// MultipartPostMethod filePost = new MultipartPostMethod(msUrl);
		// 若上传的文件比较大 , 可在此设置最大的连接超时时间
		client.getHttpConnectionManager().getParams().setConnectionTimeout(8000);

		try {
			// StringPart sp = new StringPart("sex", "male");
			// FilePart fp = new FilePart(file.getName(), file);
			FilePart fp = new FilePart("uploadedFile", file);

			MultipartRequestEntity mrp = new MultipartRequestEntity(new Part[] { fp }, filePost.getParams());
			filePost.setRequestEntity(mrp);

			// 使用系统提供的默认的恢复策略
			filePost.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());

			int httpStat = client.executeMethod(filePost);
			System.out.println("httpStat----" + httpStat);
			if (!(httpStat == HttpStatus.SC_OK)) {
				fromAgentResult = "connected fail:" + httpStat;
			} else if (httpStat == HttpStatus.SC_OK) {
				try {
					fromAgentResult = filePost.getResponseBodyAsString();
					System.out.println("发送请求完毕，接收状态：" + fromAgentResult);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (HttpException e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		} catch (IOException e) {
			log.error(e.getMessage());
			throw new RuntimeException(e);
		}
		filePost.releaseConnection();
		return fromAgentResult;
	}
	
	/**
	 * 数据流转字符串
	 * @param is 数据流
	 * @param encode 编码方式
	 * @return
	 */
	public static String streamToString(InputStream is, String encode) throws IOException {
		StringBuffer result = new StringBuffer();
		BufferedReader in = null;
		
		if (is == null) {
			return null;
		}
		try {
			String inputLine;
			in = new BufferedReader(new InputStreamReader(is, encode));
			
			while ((inputLine = in.readLine()) != null) {
				result.append(inputLine.replaceAll("\r\n\r\n", "").replaceAll("\t", ""));
			}
		} finally {
			if (in != null) {
				in.close();
			}
		}
		return result.toString();
	}
	
	public static String HttpsPost(String url,String param) throws NoSuchAlgorithmException, KeyManagementException, IOException{
		X509TrustManager trustManager = new X509TrustManager() {
			   public void checkClientTrusted(X509Certificate[] chain,
			     String authType) throws CertificateException {
			   }
			   public void checkServerTrusted(X509Certificate[] chain,
			     String authType) throws CertificateException {
			   }
			   public X509Certificate[] getAcceptedIssuers() {
				   return new X509Certificate[] {};
			   }
	   };
	   
	   HostnameVerifier trustAnyHostnameVerifier=new HostnameVerifier(){
			@Override
			public boolean verify(String hostname, SSLSession session) {
				// TODO Auto-generated method stub
				return true;
			}

	   };
	        
	        
	   SSLContext sslcontext = SSLContext.getInstance("SSL");
	   sslcontext.init(null, new TrustManager[] { trustManager },new java.security.SecureRandom());
	   
	   URL console = new URL(url);
	   HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
	   conn.setSSLSocketFactory(sslcontext.getSocketFactory());
	   conn.setHostnameVerifier(trustAnyHostnameVerifier);
	   conn.setDoOutput(true);
	   conn.connect();
	   DataOutputStream out = new DataOutputStream(conn.getOutputStream());
	   out.write(param.getBytes("UTF-8"));
	    
	   String result = "";
	   out.flush();
	   out.close();
	   InputStream is = conn.getInputStream();
	   if (is != null) {
	        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
	        byte[] buffer = new byte[1024*4];
	        int len = 0;
	        while ((len = is.read(buffer)) != -1) {
	     	   result += new String(buffer, 0, len,"UTF-8");
	        }
	        is.close();
	        return result;
	    }
	    return null;
	}
}